/*****************************************************************************
 * Copyright (C) Stacy Curl. All rights reserved.                            *
 * ------------------------------------------------------------------------- *
 * The software in this package is published under the terms of the BSD      *
 * style license a copy of which has been included with this distribution in *
 * the LICENSE.txt file.                                                     *
 *****************************************************************************/
package picounit.features.failures_first;

import picounit.PicoUnitException;
import picounit.TestFilter;
import picounit.features.base.FileReader;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.HashMap;
import java.util.Map;

class DefaultStatusPersister implements ProblemTracker, StatusPersister  {
	private final Map<String, ProblemCount> problemMap = new HashMap<String, ProblemCount>();

	private Class<?> startingClass;
	private TestFilter testFilter;

	public DefaultStatusPersister() {
		Runtime.getRuntime().addShutdownHook(new Thread() {
			@Override
			public void run() {
				writeCurrentStatus();
			}
		});
	}

	///////////////////////////////////////////////////////////////////////////////////////////////
	// ProblemTracker methods
	///////////////////////////////////////////////////////////////////////////////////////////////

	public int compare(Class<?> left, Class<?> right) {
		return problemCount(left).compareTo(problemCount(right));
	}

	public void increaseFailures(Class<?> testClass) {
		problemCount(testClass).increaseFailures();
	}

	public void increaseErrors(Class<?> testClass) {
		problemCount(testClass).increaseErrors();
	}
	
	///////////////////////////////////////////////////////////////////////////////////////////////
	// StatusPersister methods
	///////////////////////////////////////////////////////////////////////////////////////////////

	public void inform(Class<?> startingClass, TestFilter testFilter) {
		this.startingClass = startingClass;
		this.testFilter = testFilter;

		readPreviousStatus();
	}

	///////////////////////////////////////////////////////////////////////////////////////////////
	// Implementation methods
	///////////////////////////////////////////////////////////////////////////////////////////////
	
	@SuppressWarnings({"unchecked","unchecked"})
	private void readPreviousStatus() {
		try {
			for (String currentLine : new FileReader().readLines(statusFile())) {
				new ProblemCount(currentLine).addTo(problemMap);
			}
		}
		catch (IOException e) {
			throw new PicoUnitException(e);
		}
	}

	private void writeCurrentStatus() {
		try {
			File picoUnitUserDirectory = picoUnitUserDirectory();

			if (!picoUnitUserDirectory.exists() || picoUnitUserDirectory.isFile()) {
				picoUnitUserDirectory.createNewFile();

				picoUnitUserDirectory.delete();

				picoUnitUserDirectory = new File(picoUnitUserDirectory + "/");

				picoUnitUserDirectory.mkdir();
			}

			BufferedWriter bufferedWriter =
				new BufferedWriter(new OutputStreamWriter(new FileOutputStream(statusFile(), false)));

			for (ProblemCount problemCount : problemMap.values()) {
				problemCount.writeExternal(bufferedWriter);
			}

			bufferedWriter.close();
		}
		catch (IOException ioException) {
			throw new PicoUnitException(ioException);
		}
	}

	private File picoUnitUserDirectory() {
		return new File(System.getProperty("user.home"), "picoUnit");
	}

	private File statusFile() {
		return new File(picoUnitUserDirectory(),
			startingClass.getName() + "-" + testFilter.toString() + "-status.txt");
	}

	private ProblemCount problemCount(Class<?> testClass) {
		return ProblemCount.getOrCreate(problemMap, testClass);
	}
}
